package com.yale.elasticsearch.utils;


import co.elastic.clients.elasticsearch._types.query_dsl.*;
import co.elastic.clients.json.JsonData;
import com.yale.elasticsearch.model.request.QuerySearch;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @author :yale
 * @date : 2024/8/5
 */
@Component
public class ElasticsearchQueryBuilder {

    private List<Query> mustQueries;
    private List<Query> filterQueries;

    public ElasticsearchQueryBuilder() {
        this.mustQueries = new ArrayList<>();
        this.filterQueries = new ArrayList<>();
    }

    /**
     * 添加文本匹配查询
     * @param field  字段名
     * @param keyword 关键字
     * @return 当前实例
     */
    public ElasticsearchQueryBuilder addMatchQuery(String field, String keyword) {
        if (field != null && !field.isEmpty() && keyword != null && !keyword.isEmpty()) {
            mustQueries.add(MatchQuery.of(m -> m
                    .field(field)
                    .query(keyword)
            )._toQuery());
        }
        return this;
    }
    /**
     * 添加多字段多关键字匹配查询
     * @param queries  字段名列表
     * @return 当前实例
     */
    public ElasticsearchQueryBuilder addMultiMatchQuery(List<QuerySearch> queries) {
        if (queries != null && queries.size() > 0) {
            for (QuerySearch query : queries) {
                mustQueries.add(MultiMatchQuery.of(m -> m
                        .fields(query.getKey())
                        .query(query.getValue())
                )._toQuery());
            }
        }
        return this;
    }
    /**
     * 添加同一字段的多关键字匹配查询
     * @param field    字段名
     * @param keywords 关键字列表
     * @return 当前实例
     */
    public ElasticsearchQueryBuilder addMultiKeywordMatchQuery(String field, List<String> keywords) {
        if (field != null && !field.isEmpty() && keywords != null && !keywords.isEmpty()) {
            List<Query> shouldQueries = new ArrayList<>();
            for (String keyword : keywords) {
                shouldQueries.add(MatchQuery.of(m -> m
                        .field(field)
                        .query(keyword)
                )._toQuery());
            }
            mustQueries.add(BoolQuery.of(b -> b
                    .should(shouldQueries)
            )._toQuery());
        }
        return this;
    }
    /**
     * 添加数值范围过滤
     * @param field 字段名
     * @param min   最小值
     * @param max   最大值
     * @return 当前实例
     */
    public ElasticsearchQueryBuilder    addRangeFilterForNumber(String field, Double min, Double max) {
        if (field != null && !field.isEmpty() && (min != null || max != null)) {
            RangeQuery.Builder rangeQueryBuilder = new RangeQuery.Builder().field(field);
            if (min != null) {
                rangeQueryBuilder = rangeQueryBuilder.gte(JsonData.of(min));
            }
            if (max != null) {
                rangeQueryBuilder = rangeQueryBuilder.lte(JsonData.of(max));
            }
            filterQueries.add(rangeQueryBuilder.build()._toQuery());
        }
        return this;
    }
    /**
     * 添加日期范围过滤
     * @param field     字段名
     * @param startDate 起始日期（yyyy-MM-dd 格式）
     * @param endDate   结束日期（yyyy-MM-dd 格式）
     * @return 当前实例
     */
    public ElasticsearchQueryBuilder addDateRangeFilterForDate(String field, String startDate, String endDate) {
        if (field != null && !field.isEmpty() && (startDate != null || endDate != null)) {
            RangeQuery.Builder rangeQueryBuilder = new RangeQuery.Builder().field(field);
            rangeQueryBuilder.format("yyyy-MM-dd");
            if (startDate != null && !startDate.isEmpty()) {
                rangeQueryBuilder = rangeQueryBuilder.gte(JsonData.of(startDate));
            }
            if (endDate != null && !endDate.isEmpty()) {
                rangeQueryBuilder = rangeQueryBuilder.lte(JsonData.of(endDate));
            }

            filterQueries.add(rangeQueryBuilder.build()._toQuery());
        }
        return this;
    }
    /**
     * 添加布尔值过滤
     * @param field 字段名
     * @param value 布尔值
     * @return 当前实例
     */
    public ElasticsearchQueryBuilder addBooleanFilter(String field, Boolean value) {
        if (field != null && !field.isEmpty() && value != null) {
            filterQueries.add(TermQuery.of(t -> t
                    .field(field)
                    .value(value)
            )._toQuery());
        }
        return this;
    }

    /**
     * 构建 BoolQuery
     * @return BoolQuery 对象
     */
    public BoolQuery build() {
        return BoolQuery.of(b -> b
                .must(mustQueries)
                .filter(filterQueries)
        );
    }
}